package com.sj.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sj.common.dto.article.ArticleQueryParam;
import com.sj.common.exception.CustomException;
import com.sj.entity.Article;
import com.sj.entity.ArticleLabel;
import com.sj.entity.Label;
import com.sj.entity.User;
import com.sj.mapper.ArticleMapper;
import com.sj.service.ArticleLabelService;
import com.sj.service.ArticleService;
import com.sj.service.LabelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文章表 服务实现类
 * </p>
 *
 * @author 孙峻
 * @since 2022-03-09
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private LabelService labelService;

    @Autowired
    private ArticleLabelService articleLabelService;

    @Autowired
    private ArticleMapper articleMapper;

    @Override
    @Transactional(rollbackFor = CustomException.class)
    public boolean saveArticle(Article article, String tags) {
        try {
            // 保存文章信息
            boolean articleResult = this.saveOrUpdate(article);
            // 检查文章与标签id信息，并且获取到所有的标签id
            List<Integer> allLabelId = this.checkArticleLabel(tags, article);
            // 绑定标签文章
            List<ArticleLabel> articleLabelList = allLabelId.stream().map(temp -> {
                ArticleLabel articleLabel = new ArticleLabel();
                articleLabel.setArticleId(article.getId());
                articleLabel.setLabelId(temp);
                return articleLabel;
            }).collect(Collectors.toList());

            // 删除所有与该文章关联的标签
            articleLabelService.remove(Wrappers.<ArticleLabel>lambdaQuery().eq(ArticleLabel::getArticleId, article.getId()));
            // 重新添加
            boolean articleLabelResult = articleLabelService.saveBatch(articleLabelList);

            return articleLabelResult && articleResult;
        } catch (Exception e) {
            throw new CustomException("保存文章时出现了未知错误");
        }
    }

    @Override
    public Long getUserArticleNum(Integer id, String type) {
        return this.lambdaQuery().eq(Article::getUserId, id).eq(Article::getType, type).count();
    }

    @Override
    public IPage<Article> getFixTypeArticleByPage(User user, String type, IPage<Article> articlePage) {
        return this.lambdaQuery().eq(Article::getUserId, user.getId()).eq(Article::getType, type).page(articlePage);
    }

    @Override
    public IPage<Article> getHotArticleList(IPage<Article> page, String type) {
        return articleMapper.getHotArticleList(page, type);
    }

    @Override
    public IPage<Article> getAttentionArticleList(IPage<Article> page, Integer uid) {

        return articleMapper.getAttentionArticleList(page, uid);
    }

    @Override
    public IPage<Article> getRecommendList(String type, Integer uid, IPage<Article> page) {
        return articleMapper.getRecommendList(page, type, uid);
    }

    @Override
    public IPage<Article> getFixTagArticle(List<String> trueTag, String type, IPage<Article> page) {

        return articleMapper.getFixTagArticle(page, trueTag, type);
    }

    @Override
    public IPage<Article> getAdminArticleList(ArticleQueryParam articleQueryParam, IPage<Article> page) {
        return articleMapper.getAdminArticleList(page, articleQueryParam);
    }

    /**
     * 检查文章标签信息
     *
     * @param tags
     * @param article
     * @return
     */
    private List<Integer> checkArticleLabel(String tags, Article article) {
        // 分割所有的标签名字
        List<String> labelNames = Arrays.asList(tags.split(","));
        // 获取到已有的标签
        List<Label> haveLabel = labelService.lambdaQuery().in(Label::getLabelName, labelNames).eq(Label::getUserId, article.getUserId()).list();
        // 获取到已有标签的名字
        List<String> haveLabelName = haveLabel.stream().map(temp -> temp.getLabelName()).collect(Collectors.toList());

        // 获取到没有的标签的名字
        List<Label> noLabel = labelNames.stream().map(temp -> {
            Label label = null;
            if (!haveLabelName.contains(temp)) {
                label = new Label();
                label.setLabelName(temp);
                label.setUserId(article.getUserId());
            }
            return label;
        }).collect(Collectors.toList());

        // 将没有的标签名字添加到数据库
        if (noLabel.size() > 0) {
            noLabel = this.saveArticleNoLabel(noLabel);
        }

        // 获取到已有标签id 和 刚刚添加的标签id 绑定博客 与标签的信息
        List<Integer> haveId = haveLabel.stream().map(temp -> temp.getId()).collect(Collectors.toList());
        List<Integer> justAddId = noLabel.stream().map(temp -> temp.getId()).collect(Collectors.toList());
        List<Integer> allIds = CollUtil.addAllIfNotContains(haveId, justAddId);
        return allIds;
    }

    /**
     * 添加没有的标签
     *
     * @param noLabel 标签列表
     * @return
     */
    private List<Label> saveArticleNoLabel(List<Label> noLabel) {
        noLabel = noLabel.stream().filter(temp -> temp != null).collect(Collectors.toList());
        labelService.saveBatch(noLabel);
        return noLabel;
    }
}
